jQuery.fn.textile = function() {
    this.each(function() {
        var dirty = $(this).val();
        $(this).after('<div id="tmp_html"></div');
        var container = $('#tmp_html');
        var brk = '{break}';
        var dblbrk = '{dblbreak}';
        container.hide().html(dirty);
        container.find('ul').each(function(){
            var items = '';
            $(this).find('li').each(function() {
                items += '* ' + $(this).html() + brk;
            });
            $(this).replaceWith(brk + items + dblbrk);
        });
        container.find('ol').each(function(){
            var items = '';
            $(this).find('li').each(function() {
                items += '# ' + $(this).html() + brk;
            });
            $(this).replaceWith(brk + items + dblbrk);
        });
        
        container.find('h1').each(function(){
            $(this).replaceWith('h1. ' + $(this).html() + dblbrk);
        });
        container.find('h2').each(function(){
            $(this).replaceWith('h2. ' + $(this).html() + dblbrk);
        });
        container.find('h3').each(function(){
            $(this).replaceWith('h3. ' + $(this).html() + dblbrk);
        });
        container.find('p').each(function(){
            $(this).replaceWith($(this).html() + brk);
        });

        var textile = container.html();
        textile = textile.replace(/ +(?= )/g,'');
        textile = textile.replace(/    \*/g, '*');
        textile = textile.replace(new RegExp(brk, 'g'), '\n');
        textile = textile.replace(new RegExp('\t', 'g'), '');
        textile = textile.replace(new RegExp('  ', 'g'), ' ');
        textile = textile.replace(new RegExp('\\n ', 'g'), '\n');
        textile = textile.replace(new RegExp(dblbrk, 'g'), '\n');
        textile = textile.replace(new RegExp('\\n\\n', 'g'), '\n');
        $(this).val($.trim(textile));
        container.remove();
    });
}

